package cn.wx.scholar.neo4j.repository;

import java.util.List;
import java.util.Set;
import org.neo4j.ogm.model.Result;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
/*import org.springframework.data.neo4j.repository.GraphRepository;*/
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import cn.wx.scholar.neo4j.entity.Expert;

@Repository
public interface ExpertRepository extends Neo4jRepository<Expert,Long>{
	

	/**
	 * 查询一个专家的详情
	 * @param id
	 * @return
	 */
	@Query("match(e:expert) where ID(e)={id} return e")
	Expert findOneById(@Param("id") Long id);
	
	/**
	 * 根据fId 查询一个专家
	 * @param id
	 * @return
	 */
	@Query("match(e:expert) where e.fId = {fId} return e")
	Expert findByfId(@Param("fId") Long fId);

	
	@Query("match (e:expert)-[:publish1]->(p:paper)<-[:publish1]-(e1:expert) where id(e)={id} and id(e1)<>{id} "
			+ " and e.name is not null "
			+ " and e1.name is not null "
			+ " return e1 limit 100")
	List<Expert> getRelateExpert1(@Param("id") Long id);
	
	@Query("match (e:expert)-[:write1]->(b:book)<-[:write1]-(e1:expert) where id(e)={id} and id(e1)<>{id} "
			+ " and e.name is not null "
			+ " and e1.name is not null "
			+ " return e1 limit 100")
	List<Expert> getRelateExpert2(@Param("id") Long id);
	
	@Query("match (e:expert)-[:invention]->(p:patents)<-[:invention]-(e1:expert) where id(e)={id} and id(e1)<>{id} "
			+ " and e.name is not null "
			+ " and e1.name is not null "
			+ "return e1 limit 100")
	List<Expert> getRelateExpert3(@Param("id") Long id);
	
	/**
     * 根据搜索条件获取nIndex降序前num的专家
     */
	@Query("match (e:expert) where e.name =~ {name} or e.fos=~ {name} or e.authorsOrg=~ {name} return distinct e order by e.nIndex desc limit {num}")
	List<Expert> getAllExpertByName(@Param("name") String name, @Param("num") Integer num);
	
	/**
     * 根据专家A的ID和专家B的名字找出最短路径(有关系只代表合作书，论文和专利，不包含机构和领域)
     */
	@Query("match (e1:expert), (e2:expert), e=allshortestpaths((e1)-[r:publish1|write1|invention*..6]-(e2)) where id(e1) = {expert1Id} and id(e2)={expert2Id} return e")
	Result getRelationForTwoExperts(@Param("expert1Id") Long expert1Id, @Param("expert2Id") Long expert2Id);
	
	/**
     * 根据专家A的ID和机构的名字找出最短路径
     */
	@Query("match (e1:expert), (o:org), e=allshortestpaths((e1)-[*..10]-(e2)) where id(e1) = {expert1Id} and o.name = {orgName} return e limit 3")
	Result getRelationForExpertAndOrg(@Param("expert1Id") String expert1Id, @Param("orgName") String orgName);

	@Query("match (o:org)-[r:jobin]->(e:expert) where ID(o)={orgId} return e order by e.nIndex desc limit {num}")
	List<Expert> getAllExpertByOrgName(@Param("orgId") Long orgId, @Param("num") Integer num);
	
	/**
     * 根据专家Id查询每个年度的期刊的数量
     */
	@Query("match(e:expert)-[r:publish1]-(p:paper) where e.fId={fId} and  p.docType='1' with p.year as year,count(p) as c,'Journal' as type return year,c,type order by year")
	Result getJournalByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的会议的数量
     */
	@Query("match(e:expert)-[r:publish1]-(p:paper) where e.fId={fId} and p.docType='3' with p.year as year,count(p) as c,'Conference' as type return year,c,type order by year")
	Result getConferenceByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的图书的数量
     */
	@Query("match(e:expert)-[r:write1]-(b:book) where e.fId={fId} with b.year as year,count(b) as c,'book' as type return year,c,type order by year")
	Result getBookByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的新闻的数量
     */
	@Query("match(e:expert)-[r:about]-(n:news) where e.fId={fId} with n.year as year,count(n) as c,'news' as type  return year,c,type order by year")
	Result getNewsByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的社交的数量
     */
	@Query("match(e:expert)-[r:about]-(s:social) where e.fId={fId} with s.year as year,count(s) as c,'social' as type  return year,c,type order by year")
	Result getSocialByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的专利引用的数量
     */
	@Query("match(e:expert)-[r:invention]-(s:patents) where e.fId={fId} with s.fYear as year,sum(s.cit) as c,'PatentCit' as type  return year,c,type order by year")
	Result getPatentCitByYear(@Param("fId") Long fId);
	
	/**
     * 根据专家Id查询每个年度的专利的数量
     */
	@Query("match(e:expert)-[r:invention]-(s:patents) where e.fId={fId} with s.fYear as year,count(s) as c,'Patent' as type  return year,c,type order by year")
	Result getPatentByYear(@Param("fId") Long fId);
	
	
	/**
	 * 二级页面相似专家搜索
	 * book、paper 合作的
	 * @param queryName
	 * @return
	 */
	@Query(" match (e:expert)-[:publish1]->(p:paper)<-[:publish1]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} return distinct e.name,e1.name,e.pnum,e1.pnum,id(e),id(e1)"
			+ " union "
			+ " match (e:expert)-[:write1]->(b:book)<-[:write1]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} return distinct e.name,e1.name,e.pnum,e1.pnum,id(e),id(e1)"
			+ " union "
			+ " match (e:expert)-[:invention]->(p:patents)<-[:invention]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} return distinct e.name,e1.name,e.pnum,e1.pnum,id(e),id(e1)")
	Result getRelateExpertByIds(@Param("ids") Long[] ids);
	
	/**
	 * 一起写过图书的
	 * @param ids
	 * @return
	 */
	@Query(" match (e:expert)-[:write1]->(b:book)<-[:write1]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} "
			+ " return distinct e.name as ename,e1.name as rname,"
			+ " e.pnum as epnum,e1.pnum as rpnum,id(e) as eId,id(e1) as rId")
	Result getRelateBookExpertByIds(@Param("ids") Set<Long> ids);
	
	/**
	 * 一起发表论文的
	 * @param ids
	 * @return
	 */
	@Query(" match (e:expert)-[:publish1]->(p:paper)<-[:publish1]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} "
			+ " return distinct e.name as ename,e1.name as rname,"
			+ " e.pnum as epnum,e1.pnum as rpnum,id(e) as eId,id(e1) as rId")
	Result getRelatePaperExpertByIds(@Param("ids") Set<Long> ids);
	
	
	/**
	 * 一起发明专利的
	 * @param ids
	 * @return
	 */
	@Query(" match (e:expert)-[:invention]->(p:patents)<-[:invention]-(e1:expert) where id(e) in {ids} and id(e1) in {ids} "
			+ " return distinct e.name as ename,e1.name as rname,"
			+ " e.pnum as epnum,e1.pnum as rpnum,id(e) as eId,id(e1) as rId")
	Result getRelatePatentsExpertByIds(@Param("ids") Set<Long> ids);
	

	@Query(" match (e:expert) where id(e) in {ids} return e")
	Result getExpertByIds(@Param("ids") Long[] ids);
	
	/**
	 * 根据机构
	 */
	@Query("match (o:org)-[r:jobin]-(e:expert) where ID(o)={orgId} return e")
	List<Expert> getExpertByOrg(@Param("orgId") Long orgId);
	
	/**
	 * 根据人名查专家
	 */
	@Query("match (e:expert) where e.lowerName={name} return e")
	List<Expert> getExpertByName(@Param("name") String name);
	
	/**
	 * 与ids专家合作的另外一部分nIndex排名靠前num的专家
	 * @param orgName
	 * @return
	 */
	@Query(" match (e:expert)-[:publish1]->(p:paper)<-[:publish1]-(e1:expert) where id(e) in {ids} and not id(e1) in {ids} return id(e1) order by e1.nIndex desc limit {num}"
			+ " union "
			+ " match (e:expert)-[:write1]->(b:book)<-[:write1]-(e1:expert) where id(e) in {ids} and not id(e1) in {ids} return id(e1) order by e1.nIndex desc limit {num}"
			+ " union "
			+ " match (e:expert)-[:invention]->(p:patents)<-[:invention]-(e1:expert) where id(e) in {ids} and not id(e1) in {ids} return id(e1) order by e1.nIndex desc limit {num}"
			)
	List<Long> getAnotherExpertByIds(@Param("ids") Long[] ids, @Param("num") Integer num);
	/**
	 * nIds,mIds专家的合作关系
	 * @param queryName
	 * @return
	 */
	@Query(" match (e:expert)-[:publish1]->(p:paper)<-[:publish1]-(e1:expert) where id(e) in {nIds} and id(e1) in {mIds} return distinct e.name,e1.name,e.pnum,e1.pnum,id(e),id(e1) "
			+ " union "
			+ " match (e:expert)-[:write1]->(b:book)<-[:write1]-(e1:expert) where id(e) in {nIds} and id(e1) in {mIds} return distinct e.name,e1.name,e.pnum,e1.pnum,id(e),id(e1) "
			)
	Result getRelateExpertByDoubleIds(@Param("nIds") Long[] nIds, @Param("mIds") Long[] mIds);
	
	/**
	 * 查询maxhindex,maxpnum,maxcitations,maxbnum,maxnnum,maxsnum,
	 * maxefpData,maxeqWorkData,maxeqWork4Data,maxpatentsCit,maxpatentsNum
	 * @param queryName
	 * @return
	 */
	@Query("match(e:expert) return max(e.`h-index`) as hIndex,max(e.pnum) as pnum,max(e.citations) as citations,"
			+ "max(e.bnum) as bnum,max(e.nnum) as nnum,max(e.snum) as snum,"
			+ "2135 as maxefpData,145 as maxeqWorkData,15990 as maxeqWork4Data,"
			+ "169123 as patcitnum,1599 as patnum")
	Result queryMax();
	
	/**
	 * 计算该年份的pIndex
	 * @param queryName
	 * @return
	 */
	@Query("match(e:expert)-[r:about]-(n:news) " + 
			"where n.pubTime =~{year} and ID(e)={id} " + 
			"with e.name as name,count(n) as nnum " + 
			"match(e:expert)-[r:about]-(s:social) " + 
			"where s.time =~{year} and ID(e)={id} " + 
			"with e.name as name,count(s) as snum,nnum " + 
			"match(e:expert) " + 
			"with " + 
			"max(e.nnum) as maxnnum,max(e.snum) as maxsnum,nnum,snum " + 
			"with " + 
			"((log(nnum+1.0)/log(maxnnum)*0.6+log(snum+1.0)/log(maxsnum)*0.4)*100) as pIndex " + 
			"return pIndex")
	Result queryPIndexTrend(@Param("year") String year,@Param("id") Long id);
	
	@Query("match(e:expert) where e.fId={fId} with e,"
			+ " case e.viewCou is null when true then 1 else e.viewCou+1 end as h "
			+ " set e.viewCou=h ")
	void addViewCou(@Param("fId") Long fId);
}